﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// NotReviewedButNeeded
#pragma once

#include "GcmpDbCommonEdit.h"
#include "ContainerUtil.h"
#include "ElementId.h"
#include <vector>
#include "Vector3d.h"

namespace gcmp
{
    class IDocument;
    class ICurve3d;
    class IPlane;
    class IPolyCurve;
    class Coordinate3d;

    /// \brief 偏移操作的工具类。
    /// 
    /// 偏移目前支持两种方式，一种是按固定距离偏移；另一种是拾取两个点确定偏移距离。
    /// 被偏移对象需要实现IElementOffsetStrategy接口。
    class GCMP_DB_COMMON_EDIT_EXPORT OffsetUtils
    {
    public:
#pragma region Static
        /// \brief 为固定距离偏移创建偏移曲线。
        ///
        /// \param pDocument 偏移操作的文档。
        /// \param pWorkPlane 偏移操作的工作平面。
        /// \param referencePoint 固定偏移的参考点，用来确定偏移的方向，一般当前鼠标点来作为参考点。
        ///   参考点在偏移对象基线的哪一侧，则所有对象往哪一侧偏移。
        ///   如果参考点在偏移对象的基线上，无法生成固值偏移曲线。
        /// \param currentGraphicsNodeReferences 当前的图形引用节点，可以是一个也可以是多个连续线性对象。
        /// \param offsetValue 固定偏移距离
        /// \param elementOffsetCurves 偏移对象Id对应其偏移后的曲线的数组。如果ElementId是非法，则该曲线是新增曲线。
        ///    若Curve指针为空，则该对象偏移后被删除。
        /// \return 创建成功则返回true，否则返回false。
        static bool CreateOffsetCurvesByFixedValue(IDocument* pDocument
            , const IPlane* pWorkPlane
            , const Vector3d& referencePoint
            , const GraphicsNodeReferenceOwnerPtrVector& currentGraphicsNodeReferences
            , double offsetValue
            , std::vector<std::pair<ElementId, std::vector<OwnerPtr<ICurve3d>>>>& elementOffsetCurves);

        /// \brief 多段线固定距离偏移
        ///
        /// \param pPolyCurve 待偏移的多段线几何数据。
        /// \param coord 多段线偏移操作所在坐标系。
        /// \param referencePoint 固定偏移的参考点，用来确定偏移的方向，一般当前鼠标点来作为参考点。
        ///   参考点在偏移对象基线的哪一侧，则所有对象往哪一侧偏移。
        ///   如果参考点在偏移对象的基线上，无法生成固值偏移曲线。
        /// \param offsetValue 固定偏移距离
        /// \param offsetPolyCurves 多段线偏移结果
        /// \return 创建成功则返回true，否则返回false。
        static bool CreateOffsetPolyCurvesByFixedValue(const IPolyCurve* pPolyCurve
            , const Coordinate3d& coord
            , const Vector3d& referencePoint
            , double offsetValue
            , std::vector<OwnerPtr<IPolyCurve>>& offsetPolyCurves);

        /// \brief 拾取两点创建偏移曲线。
        ///
        /// 根据拾取的两个点确定偏移距离和偏移方向。第一点到第二点的方向决定偏移的参考方向;
        ///   第一点到第二点的方向朝向偏移对象的那一侧，则向哪一侧偏移。
        ///   偏移距离是第一点到第二点的距离在偏移方向的投影。
        ///
        /// \param pDocument 偏移操作的文档。
        /// \param pWorkPlane 偏移操作的工作平面。
        /// \param firstPoint 偏移的第一个点。
        /// \param secondPoint 偏移的第二个点。
        /// \param currentGraphicsNodeReferences 当前的图形引用节点，可以是一个也可以是多个连续线性对象。
        /// \param elementOffsetCurves 偏移对象Id对应其偏移后的曲线的数组。如果ElementId是非法，则该曲线是新增曲线。
        ///    若Curve指针为空，则该对象偏移后被删除。
        /// \return 创建成功则返回true，否则返回false。
        static bool CreateOffsetCurvesByTwoPoint(IDocument* pDocument
            , const IPlane* pWorkPlane
            , const Vector3d& firstPoint
            , const Vector3d& secondPoint
            , const GraphicsNodeReferenceOwnerPtrVector& currentGraphicsNodeReferences
            , std::vector<std::pair<ElementId, std::vector<OwnerPtr<ICurve3d>>>>& elementOffsetCurves);

        /// \brief 根据拾取点创建偏移多段线。
        ///
        /// \param pPolyCurve 待偏移的多段线几何数据。
        /// \param coord 多段线所在坐标系。
        /// \param pickedPoint 拾取点。
        /// \param offsetPolyCurves 多段线偏移结果
        /// \return 创建成功则返回true，否则返回false。
        static bool CreateOffsetPolyCurvesByPoint(
            const IPolyCurve* pPolyCurve
            , const Coordinate3d& coord
            , const Vector3d& pickedPoint
            , std::vector<OwnerPtr<IPolyCurve>>& offsetPolyCurves);

        /// \brief 根据偏移对象和偏移后曲线的对应关系，偏移对象。
        ///
        /// \param pDocument 当前文档。
        /// \param pWorkPlane 偏移操作的工作平面。
        /// \param bIsCopy 偏移时是否拷贝。
        /// \param elementOffsetCurves 偏移对象Id对应其偏移后的曲线的数组
        /// \param elementIdsAfterOffset 最终偏移后的ElementId。
        /// \return 成功则返回true，否则返回false。
        static bool OffsetElements(gcmp::IDocument* pDocument
            , const IPlane* pWorkPlane
            , bool bIsCopy
            , const std::vector<std::pair<ElementId, std::vector<OwnerPtr<ICurve3d>>>>& elementOffsetCurves
            , std::vector<ElementId>& elementIdsAfterOffset);

        /// \brief 根据多段线偏移结果，偏移对应的Element。
        ///
        /// \param pDocument 当前文档。
        /// \param pWorkPlane 偏移操作的工作平面。
        /// \param bIsCopy 偏移时是否拷贝。
        /// \param selectedElementId 偏移的ElementId。
        /// \param offsetPolyCurves 多段线偏移结果
        /// \param elementIdsAfterOffset 最终偏移后的ElementId。
        /// \return 成功则返回true，否则返回false。
        static bool OffsetElements(gcmp::IDocument* pDocument
            , const IPlane* pWorkPlane
            , bool bIsCopy
            , const ElementId& selectedElementId
            , const std::vector<OwnerPtr<IPolyCurve>>& offsetPolyCurves
            , std::vector<ElementId>& elementIdsAfterOffset);
#pragma endregion Static
    };
}

